<template>
  <div style="width:100%">
    <div>
      <el-form-item label="角色名称">
        <el-input v-model="keyword" placeholder="请输入角色名称" />
      </el-form-item>
    </div>
    <div>
      <el-button size="small" type="primary" @click="fetchData">
        搜索
      </el-button>
      <el-button size="small" @click="reset">
        重置
      </el-button>
    </div>
    <div style="margin:10px">
      <el-button type="success" size="small" @click="showSaveRoleDialog">
        添加
      </el-button>
    </div>
    <div>
      <el-table :data="roleList" border style="width: 100%">
        <el-table-column prop="roleName" label="角色名称" width="180" />
        <el-table-column prop="roleCode" label="角色code" width="180" />
        <el-table-column prop="createTime" label="创建时间" />
        <el-table-column label="操作">
          <template #default="scope">
            <el-button type="primary" @click="handleEdit(scope.row)">
              修改
            </el-button>
            <el-button type="danger" @click="handleDelete(scope.row)">
              删除
            </el-button>
            <el-button
              type="warning"
              @click="handleShowAssignMenusDialog(scope.row)"
            >
              分配菜单
            </el-button>
          </template>
        </el-table-column>
      </el-table>
    </div>
    <!-- 分页导航条 -->
    <div style="margin-top:20px;">
      <el-pagination
        v-model:current-page="pageNum"
        v-model:page-size="pageSize"
        :page-sizes="[1, 2, 3, 4, 5]"
        layout="total, sizes, prev, pager, next, jumper"
        :total="total"
        @size-change="fetchData"
        @current-change="fetchData"
      />
    </div>

    <!-- 新增或更新角色对话框 -->
    <el-dialog v-model="dialogFormVisible" :title="title">
      <el-form :model="sysRole">
        <el-form-item label="角色名称" :label-width="formLabelWidth">
          <el-input v-model="sysRole.roleName" autocomplete="off" />
        </el-form-item>
        <el-form-item label="角色code" :label-width="formLabelWidth">
          <el-input v-model="sysRole.roleCode" autocomplete="off" />
        </el-form-item>
        <el-form-item label="角色介绍" :label-width="formLabelWidth">
          <el-input v-model="sysRole.description" autocomplete="off" />
        </el-form-item>
      </el-form>
      <template #footer>
        <span class="dialog-footer">
          <el-button @click="dialogFormVisible = false">取消</el-button>
          <el-button type="primary" @click="handleSaveOrUpdateRole">
            提交
          </el-button>
        </span>
      </template>
    </el-dialog>
    <!-- 分配菜单的对话框： 通过可选择的树形控件展示菜单列表 已拥有的默认选中 -->
    <el-dialog v-model="dialogAssignMenusVisible" title="分配菜单">
      <!-- 
        node-key:表示tree展示数据时使用哪个属性值当做每个节点的key： id
        default-checked-keys： 表示tree 默认选中的节点的key的值列表
        props:表示tree解析数据时 额外配置的属性

       -->
      <el-tree
        ref="tree"
        :data="menus"
        show-checkbox
        node-key="id"
        :default-expand-all="true"
        :default-checked-keys="checkedMenuIds"
        :props="defaultProps"
      />
      <el-button type="primary" @click="handleAssignMenus2Role">分配</el-button>
      <el-button @click="dialogAssignMenusVisible = false">取消</el-button>
    </el-dialog>
  </div>
</template>
<script setup>
import { ref, onMounted } from 'vue'
import { ElMessage, ElMessageBox } from 'element-plus'
//引入api模块
import {
  FindPage,
  DeleteRole,
  SaveRole,
  UpdateRole,
  GetById,
} from '@/api/sysRole'
import {
  listNestedMenusAndCheckedMenuIds,
  AssignMenus2Role,
} from '@/api/sysRoleMenu'
//=== 分配菜单start
let dialogAssignMenusVisible = ref(false)
let checkedMenuIds = ref([])
const menus = ref([])
const defaultProps = ref({
  children: 'children', //节点的子节点
  label: 'title', // 展示的每个节点的标题
})
let tree = ref({})
//分配菜单对话框分配按钮事件函数
let handleAssignMenus2Role = async () => {
  //获取页面中选中的菜单的id列表
  //树形控件.getCheckedKeys(): vue页面中的 标签只要定义ref属性值 绑定声明的响应式变量 就可以通过变量获取标签dom对象
  console.log(tree.value.getCheckedKeys())
  console.log(tree.value.getHalfCheckedKeys())
  // console.log(checkedMenuIds.value)  获取的仍然是初始化后的选择的菜单id集合 不会变
  //合并选中和半开状态的菜单id集合
  let checkedMenuIds = [
    ...tree.value.getCheckedKeys(),
    ...tree.value.getHalfCheckedKeys(),
  ]
  //角色id：
  // console.log(checkedMenuIds, role.value.id)
  await AssignMenus2Role(role.value.id, checkedMenuIds)
  ElMessage.success('菜单分配成功')
  dialogAssignMenusVisible.value = false
}
//显示分配菜单对话框
let role = ref({})
let handleShowAssignMenusDialog = async row => {
  checkedMenuIds.value = []
  //查询所有的菜单列表和当前角色已拥有的菜单
  const { data } = await listNestedMenusAndCheckedMenuIds(row.id)
  menus.value = data.menus
  role.value = row
  checkedMenuIds.value = data.checkedMenuIds
  //显示对话框：
  dialogAssignMenusVisible.value = true
}
//=== 分配菜单end

//===分页组件需要绑定的变量和函数
let pageNum = ref(1)
let pageSize = ref(3)
let total = ref(0) // 页面渲染时 第一次查询分页数据后 可以初始化total
//===
//===条件搜索的变量+函数
let keyword = ref('')
let reset = () => {
  keyword.value = ''
  pageNum.value = 1
  pageSize.value = 3
  fetchData()
}
//===删除角色事件函数
let handleDelete = row => {
  //row 代表点击按钮所在行的角色 json对象
  ElMessageBox.confirm(`删除角色【 ${row.roleName} 】，是否确认?`, '确认', {
    confirmButtonText: '确认',
    cancelButtonText: '取消',
    type: 'warning',
  })
    .then(async () => {
      //确认删除
      const { code, message } = await DeleteRole(row.id)
      if (+code === 200) {
        ElMessage({
          type: 'success',
          message: '删除成功',
        })
        //刷新页面数据
        fetchData()
      } else {
        ElMessage({
          type: 'error',
          message,
        })
      }
    })
    .catch(() => {
      //取消删除
      ElMessage({
        type: 'info',
        message: '取消删除',
      })
    })
}

//===查询分页数据函数
let fetchData = async () => {
  const { code, message, data } = await FindPage(
    pageNum.value,
    pageSize.value,
    keyword.value
  )
  if (+code === 200) {
    console.log(data)
    //分页数据列表
    roleList.value = data.list
    //总记录条数
    total.value = data.total
  } else {
    ElMessage.error(message)
  }
}
//进入页面时查询数据渲染展示
onMounted(() => {
  fetchData()
})
//角色分页数据列表
const roleList = ref([])

//对话框需要的属性和函数
let title = ref('新增角色')
let dialogFormVisible = ref(false)
let sysRole = ref({}) //数据模型：对话框绑定的对象
let formLabelWidth = '120px' //表单项label的宽度
let handleSaveOrUpdateRole = () => {
  //对话框提交按钮事件函数
  //区分新增还是更新
  if (sysRole.value.id) {
    //sysRole新增时所有数据都是空的，只有更新时从后端查询到的sysRole才包含id
    //更新
    handleUpdateRole()
  } else {
    //新增
    handleSaveRole()
  }
}
//===新增角色：
// 1、新增按钮事件函数：  弹出新增角色对话框表单
let showSaveRoleDialog = () => {
  //显示对话框
  title.value = '新增角色'
  dialogFormVisible.value = true
}
// 2、新增角色对话框提交按钮事件函数
let handleSaveRole = async () => {
  const { code, message } = await SaveRole(sysRole.value)
  if (+code === 200) {
    ElMessage.success('新增成功')
    //关闭对话框
    dialogFormVisible.value = false
    //清除缓存
    sysRole.value = {}
    //设置页码为最大页码+1 ，但是需要后端开启分页合理化
    //刷新页面数据
    fetchData()
  } else {
    ElMessage.error(message)
  }
}

//===更新角色
// 1、回显要更新的角色信息
// 修改按钮事件函数：弹出更新对话框
let handleEdit = async row => {
  //查询要更新的角色信息
  const { code, message, data } = await GetById(row.id)
  if (+code === 200) {
    sysRole.value = data
    title.value = '更新角色'
    dialogFormVisible.value = true
  } else {
    ElMessage.error(message)
  }
}
//2、更新角色的函数
let handleUpdateRole = async () => {
  const { code, message } = await UpdateRole(sysRole.value)
  if (+code === 200) {
    ElMessage.success('更新成功')
    //关闭对话框
    dialogFormVisible.value = false
    //清除缓存
    sysRole.value = {}
    //设置页码为最大页码+1 ，但是需要后端开启分页合理化
    //刷新页面数据
    fetchData()
  } else {
    ElMessage.error(message)
  }
}
</script>
